home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / text / hyper / ManualBrows1_1.lha / DynamicHost.c < prev    next >
C/C++ Source or Header  |  1994-11-12  |  29KB  |  811 lines

  1. /************************************************************************/
  2. /*                                    */
  3. /*  Copyright (C) 1994  Christian Stieber                */
  4. /*                                    */
  5. /* This program is free software; you can redistribute it and/or modify    */
  6. /* it under the terms of the GNU General Public License as published by    */
  7. /* the Free Software Foundation; either version 2 of the License, or    */
  8. /* (at your option) any later version.                    */
  9. /*                                    */
  10. /* This program is distributed in the hope that it will be useful,    */
  11. /* but WITHOUT ANY WARRANTY; without even the implied warranty of    */
  12. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    */
  13. /* GNU General Public License for more details.                */
  14. /*                                    */
  15. /* You should have received a copy of the GNU General Public License    */
  16. /* along with this program; if not, write to the Free Software        */
  17. /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.        */
  18. /*                                    */
  19. /************************************************************************/
  20. /*                                    */
  21. /* Author address:                            */
  22. /*   Christian Stieber                            */
  23. /*   Konradstraße 41                            */
  24. /*   D-85055 Ingolstadt                            */
  25. /*   (Germany)                                */
  26. /*   Phone: 0841-59896                            */
  27. /*                                    */
  28. /************************************************************************/
  29.  
  30. #ifndef V39
  31.    #define CreatePool LibCreatePool
  32.    #define DeletePool LibDeletePool
  33.    #define AllocPooled LibAllocPooled
  34.    #define FreePooled LibFreePooled
  35. #endif
  36.  
  37. #ifndef DOS_DOSEXTENS_H
  38. #include <dos/dosextens.h>
  39. #endif
  40.  
  41. #ifndef DOS_EXALL_H
  42. #include <dos/exall.h>
  43. #endif
  44.  
  45. #ifndef INTUITION_INTUITION_H
  46. #include <intuition/intuition.h>
  47. #endif
  48.  
  49. #ifndef LIBRARIES_AMIGAGUIDE_H
  50. #include <libraries/amigaguide.h>
  51. #endif
  52.  
  53. #ifndef WORKBENCH_STARTUP_H
  54. #include <workbench/startup.h>
  55. #endif
  56.  
  57. #ifndef WORKBENCH_WORKBENCH_H
  58. #include <workbench/workbench.h>
  59. #endif
  60.  
  61. #ifndef __GNUC__
  62.    #ifndef CLIB_EXEC_PROTOS_H
  63.    #include <clib/exec_protos.h>
  64.    #endif
  65.  
  66.    #ifndef CLIB_DOS_PROTOS_H
  67.    #include <clib/dos_protos.h>
  68.    #endif
  69.  
  70.    #ifndef CLIB_UTILITY_PROTOS_H
  71.    #include <clib/utility_protos.h>
  72.    #endif
  73.  
  74.    #ifndef CLIB_INTUITION_PROTOS_H
  75.    #include <clib/intuition_protos.h>
  76.    #endif
  77.  
  78.    #ifndef CLIB_ICON_PROTOS_H
  79.    #include <clib/icon_protos.h>
  80.    #endif
  81.  
  82.    #ifndef CLIB_AMIGAGUIDE_PROTOS_H
  83.    #include <clib/amigaguide_protos.h>
  84.    #endif
  85.  
  86.    #include <pragmas/exec_pragmas.h>
  87.    #include <pragmas/dos_pragmas.h>
  88.    #include <pragmas/intuition_pragmas.h>
  89.    #include <pragmas/utility_pragmas.h>
  90.    #include <pragmas/icon_pragmas.h>
  91.    #include <pragmas/amigaguide_pragmas.h>
  92. #endif
  93.  
  94. #include <string.h>
  95.  
  96. #include "Globals.h"
  97.  
  98. /************************************************************************/
  99.  
  100. #ifdef __GNUC__
  101.  
  102. #include "Inlines.h"
  103.  
  104. #ifndef V39
  105.    APTR AllocPooled(APTR, ULONG);
  106.    void FreePooled(APTR, APTR, ULONG);
  107.    APTR CreatePool(ULONG, ULONG, ULONG);
  108.    void DeletePool(APTR);
  109. #endif
  110.  
  111. #endif   /* __GNUC__ */
  112.  
  113. /************************************************************************/
  114.  
  115. #define MESSAGE_NAME    ".Message"
  116. #define CONFIG_NAME     ".Config"
  117.  
  118. /************************************************************************/
  119.  
  120. static char AboutText[]=
  121.    "\n"
  122.    "  This is the manual browser " PROGVERSION " (" PROGDATE "), " CPU " version\n"
  123. #ifdef V39
  124.    "  This executable was compiled for AmigaOS 3.0 (V39) and up.\n"
  125. #endif
  126.    "  Copyright © 1994 Christian Stieber\n"
  127.    "\n"
  128.    "\n"
  129.    "  This program is free software; you can redistribute it and/or modify\n"
  130.    "  it under the terms of the @{\x22GNU General Public License\x22 LINK COPYING/Main} as published by\n"
  131.    "  the Free Software Foundation; either version 2 of the License, or\n"
  132.    "  (at your option) any later version.\n"
  133.    "\n"
  134.    "  This program is distributed in the hope that it will be useful,\n"
  135.    "  but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
  136.    "  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
  137.    "  @{\x22GNU General Public License\x22 LINK COPYING/Main} for more details.\n"
  138.    "\n"
  139.    "  You should have received a copy of the @{\x22GNU General Public License\x22 LINK COPYING/Main}\n"
  140.    "  along with this program; if not, write to the Free Software\n"
  141.    "  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
  142.    "\n"
  143.    "\n"
  144.    "  Author: Christian Stieber\n"
  145.    "          Konradstraße 41\n"
  146.    "          D-85055 Ingolstadt\n"
  147.    "          (Germany)\n"
  148.    "\n"
  149.    "  Currently (1994) I'm a student and may reached at the following address:\n"
  150.    "\n"
  151.    "          Christian Stieber\n"
  152.    "          Seitzstraße 6, Zi. 306\n"
  153.    "          D-80538 München\n"
  154.    "          (Germany)\n"
  155.    "\n"
  156.    "          EMail: stieber@informatik.tu-muenchen.de\n"
  157.    "\n";
  158.  
  159. /************************************************************************/
  160.  
  161. struct DirNode
  162.    {
  163.       struct DirNode *Next;
  164.       struct ActionNode *ActionNode;
  165.       char Name[1];
  166.    };
  167.  
  168. /************************************************************************/
  169.  
  170. static struct DirNode *DirectoryList;
  171. static struct DirNode *FileList;
  172. static char *NodeData;
  173. static ULONG NodeLength;
  174.  
  175. static char *MessageText;
  176.  
  177. #ifdef __GNUC__
  178.    static struct FileInfoBlock FileInfoBlock __attribute__((aligned(4)));
  179. #else
  180.    static struct FileInfoBlock __aligned FileInfoBlock;
  181. #endif
  182.  
  183. static struct ActionNode *LocalActionList;
  184.  
  185. /************************************************************************/
  186.  
  187. static void InsertDirNode(struct DirNode *DirNode, struct DirNode **DirList)
  188.  
  189. {
  190.    if (!*DirList)
  191.       {
  192.          *DirList=DirNode;
  193.          DirNode->Next=NULL;
  194.       }
  195.    else
  196.       {
  197.          struct DirNode *Prev, *Current;
  198.  
  199.          Prev=(struct DirNode *)DirList;
  200.          Current=Prev->Next;
  201.          while (Current && (Stricmp(Current->Name,DirNode->Name)<0))
  202.             {
  203.                Prev=Current;
  204.                Current=Current->Next;
  205.             }
  206.          Prev->Next=DirNode;
  207.          DirNode->Next=Current;
  208.       }
  209. }
  210.  
  211. /************************************************************************/
  212.  
  213. static void FreeDirNodes(struct DirNode **DirList)
  214.  
  215. {
  216.    while (*DirList)
  217.       {
  218.          struct DirNode *Next;
  219.          Next=(*DirList)->Next;
  220.          Free(*DirList);
  221.          *DirList=Next;
  222.       }
  223. }
  224.  
  225. /************************************************************************/
  226. /*                                    */
  227. /* Look for an action node matching a given filename.            */
  228. /* Checks the local list first, followed by the global list.        */
  229. /* Returns NULL for "no action assigned"                */
  230. /*                                    */
  231. /************************************************************************/
  232.  
  233. static struct ActionNode *FindActionNode(char *Filename)
  234.  
  235. {
  236.    struct ActionNode *ActionNode;
  237.  
  238.    for (ActionNode=LocalActionList; ActionNode; ActionNode=ActionNode->Next)
  239.       {
  240.          if (MatchPatternNoCase(ActionNode->Pattern,Filename))
  241.             {
  242.                return ActionNode;
  243.             }
  244.       }
  245.  
  246.    for (ActionNode=ActionList; ActionNode; ActionNode=ActionNode->Next)
  247.       {
  248.          if (MatchPatternNoCase(ActionNode->Pattern,Filename))
  249.             {
  250.                return ActionNode;
  251.             }
  252.       }
  253.  
  254.    return NULL;
  255. }
  256.  
  257. /************************************************************************/
  258. /*                                    */
  259. /* Free the local action list                        */
  260. /*                                    */
  261. /************************************************************************/
  262.  
  263. static void FreeLocalActionList(void)
  264.  
  265. {
  266.    while (LocalActionList)
  267.       {
  268.          struct ActionNode *ThisNode;
  269.  
  270.          ThisNode=LocalActionList;
  271.          LocalActionList=ThisNode->Next;
  272.          Free(ThisNode);
  273.       }
  274. }
  275.  
  276. /************************************************************************/
  277. /*                                    */
  278. /* Read the local action list for a directory, if available.        */
  279. /*                                    */
  280. /************************************************************************/
  281.  
  282. static void ReadLocalConfig(BPTR DirLock)
  283.  
  284. {
  285.    BPTR OldCurrDir;
  286.    BPTR FileHandle;
  287.  
  288.    OldCurrDir=CurrentDir(DirLock);
  289.    if (FileHandle=Open(CONFIG_NAME,MODE_OLDFILE))
  290.       {
  291.          int Result;
  292.          Result=ReadConfigFile(FileHandle,&LocalActionList);
  293.          Close(FileHandle);
  294.          if (!Result)
  295.             {
  296.                FreeLocalActionList();
  297.             }
  298.       }
  299.    CurrentDir(OldCurrDir);
  300. }
  301.  
  302. /************************************************************************/
  303. /*                                    */
  304. /*                                    */
  305. /************************************************************************/
  306.  
  307. #define BUFFER_SIZE (4*1024)
  308.  
  309. static long ReadDir(BPTR DirLock)
  310.  
  311. {
  312.    struct ExAllControl *ExAllControl;
  313.    long DosError;
  314.  
  315.    DosError=0;
  316.    if ((ExAllControl=AllocDosObject(DOS_EXALLCONTROL,NULL)))
  317.       {
  318.          struct ExAllData *Buffer;
  319.          if ((Buffer=Malloc(BUFFER_SIZE)))
  320.             {
  321.                int more;
  322.                ReadLocalConfig(DirLock);
  323.                ExAllControl->eac_LastKey=0;
  324.                ExAllControl->eac_MatchString=NULL;
  325.                ExAllControl->eac_MatchFunc=NULL;
  326.                do
  327.                   {
  328.                      more=ExAll(DirLock,Buffer,BUFFER_SIZE,ED_TYPE,ExAllControl);
  329.                      if ((!more) && (IoErr()!=ERROR_NO_MORE_ENTRIES))
  330.                         {
  331.                            DosError=IoErr();
  332.                         }
  333.                      else
  334.                         {
  335.                            if (ExAllControl->eac_Entries)
  336.                               {
  337.                                  struct ExAllData *ExAllData;
  338.                                  ExAllData=Buffer;
  339.                                  do
  340.                                     {
  341.                                        if (Stricmp(ExAllData->ed_Name,MESSAGE_NAME) || Stricmp(ExAllData->ed_Name,CONFIG_NAME))
  342.                                           {
  343.                                              struct ActionNode *ActionNode;
  344.                                              ActionNode=FindActionNode(ExAllData->ed_Name);
  345.                                              if (!ActionNode || Stricmp(ActionNode->Action,"IGNORE"))
  346.                                                 {
  347.                                                    struct DirNode *DirNode;
  348.                                                    if (ActionNode && !Stricmp(ActionNode->Action,"DEFAULT"))
  349.                                                       {
  350.                                                          ActionNode=NULL;
  351.                                                       }
  352.                                                    if ((DirNode=Malloc(sizeof(struct DirNode)+strlen(ExAllData->ed_Name))))
  353.                                                       {
  354.                                                          DirNode->ActionNode=ActionNode;
  355.                                                          strcpy(DirNode->Name,ExAllData->ed_Name);
  356.                                                          if (ExAllData->ed_Type==ST_SOFTLINK)
  357.                                                             {
  358.                                                                BPTR LinkLock;
  359.                                                                BPTR OldCurrDir;
  360.                                                                OldCurrDir=CurrentDir(DirLock);
  361.                                                                if ((LinkLock=Lock(ExAllData->ed_Name,SHARED_LOCK)))
  362.                                                                   {
  363.                                                                      if (Examine(LinkLock,&FileInfoBlock))
  364.                                                                         {
  365.                                                                            InsertDirNode(DirNode,FileInfoBlock.fib_DirEntryType>=0 ? &DirectoryList : &FileList);
  366.                                                                         }
  367.                                                                      UnLock(LinkLock);
  368.                                                                   }
  369.                                                                CurrentDir(OldCurrDir);
  370.                                                             }
  371.                                                          else
  372.                                                             {
  373.                                                                InsertDirNode(DirNode,ExAllData->ed_Type>=0 ? &DirectoryList : &FileList);
  374.                                                             }
  375.                                                       }
  376.                                                    else
  377.                                                       {
  378.                                                          DosError=IoErr();
  379.                                                       }
  380.                                                 }
  381.                                           }
  382.                                        ExAllData=ExAllData->ed_Next;
  383.                                     }
  384.                                  while (!DosError && ExAllData);
  385.                               }
  386.                         }
  387.                   }
  388.                while (!DosError && more);
  389.                if (more)
  390.                   {
  391. #ifdef V39
  392.                      ExAllEnd(DirLock,Buffer,BUFFER_SIZE,ED_TYPE,ExAllControl);
  393. #else
  394.                      while (ExAll(DirLock,Buffer,BUFFER_SIZE,ED_TYPE,ExAllControl)) ;
  395. #endif
  396.                   }
  397.                if (DosError)
  398.                   {
  399.                      FreeDirNodes(&DirectoryList);
  400.                      FreeDirNodes(&FileList);
  401.                   }
  402.                Free(Buffer);
  403.                FreeLocalActionList();
  404.             }
  405.          else
  406.             {
  407.                DosError=IoErr();
  408.             }
  409.          FreeDosObject(DOS_EXALLCONTROL,ExAllControl);
  410.       }
  411.    else
  412.       {
  413.          DosError=IoErr();
  414.       }
  415.    return DosError;
  416. }
  417.  
  418. #undef BUFFER_SIZE
  419.  
  420. /***********************************************/
  421.  
  422. static char *NodeDataTmp;
  423.  
  424. static int PrintNodeText(char *Text)
  425.  
  426. {
  427.    if (NodeDataTmp)
  428.       {
  429.          NodeDataTmp=Stpcpy(NodeDataTmp,Text);
  430.       }
  431.    return strlen(Text);
  432. }
  433.  
  434. /***********************************************/
  435.  
  436. static int PrintDir(char *ThisDir, char *PathName)
  437.  
  438. {
  439.    int Length;
  440.    struct DirNode *Current;
  441.    short ColWidth, Columns;
  442.    short MaxLength;
  443.    short Column;
  444.  
  445.    /* Max. length of the buttons */
  446.    MaxLength=0;
  447.    for (Current=DirectoryList; Current; Current=Current->Next)
  448.       {
  449.          Length=strlen(Current->Name)+1;
  450.          if (Length>MaxLength) MaxLength=Length;
  451.       }
  452.    for (Current=FileList; Current; Current=Current->Next)
  453.       {
  454.          Length=strlen(Current->Name);
  455.          if (Length>MaxLength) MaxLength=Length;
  456.       }
  457.    if (AmigaGuideBase->lib_Version>=39) MaxLength++;
  458.  
  459.    Columns=LineLength/(MaxLength+1);
  460.    ColWidth=LineLength/Columns;
  461.    if (AmigaGuideBase->lib_Version>=39) ColWidth--;
  462.  
  463.    Length=0;
  464.  
  465.    Column=0;
  466.    for (Current=DirectoryList; Current; Current=Current->Next)
  467.       {
  468.          int CurWidth;
  469.          CurWidth=0;
  470.          Length+=PrintNodeText("@{\x22");
  471.          CurWidth+=PrintNodeText(Current->Name);
  472.          CurWidth+=PrintNodeText("/");
  473.          Length+=PrintNodeText("\x22 LINK \x22");
  474.          if (*ThisDir)
  475.             {
  476.                Length+=PrintNodeText(ThisDir);
  477.                Length+=PrintNodeText("/");
  478.             }
  479.          Length+=PrintNodeText(Current->Name);
  480.          Length+=PrintNodeText("\x22}");
  481.          Column++;
  482.          if (Column>=Columns)
  483.             {
  484.                Length+=PrintNodeText("\n");
  485.                Column=0;
  486.             }
  487.          else
  488.             {
  489.                while (CurWidth<ColWidth) CurWidth+=PrintNodeText(" ");
  490.             }
  491.          Length+=CurWidth;
  492.       }
  493.    if (Column)
  494.       {
  495.          Length+=PrintNodeText("\n");
  496.       }
  497.  
  498.    if (DirectoryList && FileList)
  499.       {
  500.          Length+=PrintNodeText("\n\n");
  501.       }
  502.  
  503.    Column=0;
  504.    for (Current=FileList; Current; Current=Current->Next)
  505.       {
  506.          int CurWidth;
  507.          CurWidth=0;
  508.          Length+=PrintNodeText("@{\x22");
  509.          CurWidth+=PrintNodeText(Current->Name);
  510.          Length+=PrintNodeText("\x22 ");
  511.          if (Current->ActionNode)
  512.             {
  513.                char *t;
  514.                char x[4];
  515.  
  516.                x[1]='\0';
  517.                for (t=Current->ActionNode->Action; *t; t++)
  518.                   {
  519.                      if (*t=='%')
  520.                         {
  521.                            switch(*(t+1))
  522.                               {
  523.                                  case '%': Length+=PrintNodeText("%");
  524.                                            t++;
  525.                                            break;
  526.  
  527.                                  case 'p': Length+=PrintNodeText(PathName);
  528.                                            t++;
  529.                                            break;
  530.  
  531.                                  case 'f': Length+=PrintNodeText(Current->Name);
  532.                                            t++;
  533.                                            break;
  534.  
  535.                                  case 'F': {
  536.                                               char *u, *v;
  537.                                               v=NULL;
  538.                                               for (u=Current->Name; *u; u++)
  539.                                                  {
  540.                                                     if (*u=='.') v=u;
  541.                                                  }
  542.                                               if (!v) v=u;
  543.                                               for (u=Current->Name; u!=v; u++)
  544.                                                  {
  545.                                                     x[0]=*u;
  546.                                                     Length+=PrintNodeText(x);
  547.                                                  }
  548.                                            }
  549.                                            t++;
  550.                                            break;
  551.  
  552.                                  default:  x[0]=*t;
  553.                                            Length+=PrintNodeText(x);
  554.                                            break;
  555.                               }
  556.                         }
  557.                      else
  558.                         {
  559.                            x[0]=*t;
  560.                            Length+=PrintNodeText(x);
  561.                         }
  562.                   }
  563.             }
  564.          else
  565.             {
  566.                Length+=PrintNodeText("LINK \x22");
  567.                if (*ThisDir)
  568.                   {
  569.                      Length+=PrintNodeText(ThisDir);
  570.                      Length+=PrintNodeText("/");
  571.                   }
  572.                Length+=PrintNodeText(Current->Name);
  573.                Length+=PrintNodeText("/Main");
  574.                Length+=PrintNodeText("\x22");
  575.             }
  576.          Length+=PrintNodeText("}");
  577.          Column++;
  578.          if (Column>=Columns)
  579.             {
  580.                Length+=PrintNodeText("\n");
  581.                Column=0;
  582.             }
  583.          else
  584.             {
  585.                while (CurWidth<ColWidth) CurWidth+=PrintNodeText(" ");
  586.             }
  587.          Length+=CurWidth;
  588.       }
  589.    if (Column)
  590.       {
  591.          Length+=PrintNodeText("\n");
  592.       }
  593.  
  594.    return Length;
  595. }
  596.  
  597. /***********************************************/
  598.  
  599. static int PrintMessage(void)
  600.  
  601. {
  602.    if (MessageText)
  603.       {
  604.          int Length;
  605.          Length=PrintNodeText(MessageText);
  606.          Length+=PrintNodeText("\n");
  607.          return Length;
  608.       }
  609.    return 0;
  610. }
  611.  
  612. /***********************************************/
  613.  
  614. static void ReadMessage(BPTR DirLock)
  615.  
  616. {
  617.    BPTR OldCurrDir;
  618.    BPTR FileHandle;
  619.  
  620.    OldCurrDir=CurrentDir(DirLock);
  621.    if ((FileHandle=Open(MESSAGE_NAME,MODE_OLDFILE)))
  622.       {
  623.          if (ExamineFH(FileHandle,&FileInfoBlock))
  624.             {
  625.                ULONG Length;
  626.  
  627.                Length=FileInfoBlock.fib_Size+1;
  628.                if (MessageText=Malloc(Length))
  629.                   {
  630.                      Read(FileHandle,MessageText,Length-1);
  631.                      MessageText[Length-1]='\0';
  632.                   }
  633.             }
  634.          Close(FileHandle);
  635.       }
  636.    CurrentDir(OldCurrDir);
  637. }
  638.  
  639. /***********************************************/
  640.  
  641. #ifdef __GNUC__
  642. ULONG AmigaGuideHostDispatcher(Msg Message)
  643. #else
  644. ULONG __saveds __asm AmigaGuideHostDispatcher(register __a1 Msg Message)
  645. #endif
  646.  
  647. {
  648.    switch(Message->MethodID)
  649.       {
  650.          case HM_FINDNODE:  {
  651.                                char *Name;
  652.  
  653.                                Name=((struct opFindHost *)Message)->ofh_Node;
  654.                                while (!Strnicmp(Name,DatabaseName,strlen(DatabaseName)))
  655.                                   {
  656.                                      Name+=strlen(DatabaseName)+1;
  657.                                   }
  658.  
  659.                                ((struct opFindHost *)Message)->ofh_Next=((struct opFindHost *)Message)->ofh_Prev=((struct opFindHost *)Message)->ofh_Node;
  660.  
  661.                                if (!Stricmp("main",Name))
  662.                                   {
  663.                                      ((struct opFindHost *)Message)->ofh_Title="Manual browser " PROGVERSION;
  664.                                   }
  665.                                else if (!strcmp("AbOuT",Name))
  666.                                   {
  667.                                      ((struct opFindHost *)Message)->ofh_Title="About the manual browser";
  668.                                   }
  669.                                else
  670.                                   {
  671.                                      BPTR OldCurrDir;
  672.                                      BPTR TestLock;
  673.  
  674.                                      OldCurrDir=CurrentDir(ManDir);
  675.                                      if ((TestLock=Lock(Name,SHARED_LOCK)))
  676.                                         {
  677.                                            UnLock(TestLock);
  678.                                         }
  679.                                      CurrentDir(OldCurrDir);
  680.                                      if (!TestLock) return FALSE;
  681.                                      ((struct opFindHost *)Message)->ofh_Title=Name;
  682.                                      ((struct opFindHost *)Message)->ofh_TOC="main";
  683.                                   }
  684.                                return TRUE;
  685.                             }
  686.                             break;
  687.  
  688.          case HM_OPENNODE:  {
  689.                                BPTR DirLock;
  690.                                BPTR OldCurrDir;
  691.                                char *Name;
  692.                                int Main;
  693.                                long DosError;
  694.  
  695.                                DosError=0;
  696.                                ((struct opNodeIO *)Message)->onm_Flags=HTNF_CLEAN;
  697.                                ((struct opNodeIO *)Message)->onm_FileName=NULL;
  698.                                Name=((struct opNodeIO *)Message)->onm_Node;
  699.                                while (!Strnicmp(Name,DatabaseName,strlen(DatabaseName)))
  700.                                   {
  701.                                      Name+=strlen(DatabaseName)+1;
  702.                                   }
  703.  
  704.                                if ((Main=!Stricmp("main",Name)))
  705.                                   {
  706.                                      Name+=4;
  707.                                   }
  708.                                else if (!strcmp("AbOuT",Name))
  709.                                   {
  710.                                      ((struct opNodeIO *)Message)->onm_DocBuffer=AboutText;
  711.                                      ((struct opNodeIO *)Message)->onm_BuffLen=sizeof(AboutText)-1;
  712.                                      return TRUE;
  713.                                   }
  714.  
  715.                                OldCurrDir=CurrentDir(ManDir);
  716.                                if ((DirLock=Lock(Name,SHARED_LOCK)))
  717.                                   {
  718.                                      char *DirName;
  719.                                      int DirNameLength;
  720.  
  721.                                      DirNameLength=256;
  722.                                      do
  723.                                         {
  724.                                            if (DirName=Malloc(DirNameLength))
  725.                                               {
  726.                                                  if (NameFromLock(DirLock,DirName,DirNameLength))
  727.                                                     {
  728.                                                        break;
  729.                                                     }
  730.                                                  if (IoErr()!=ERROR_LINE_TOO_LONG)
  731.                                                     {
  732.                                                        DosError=IoErr();
  733.                                                     }
  734.                                                  Free(DirName);
  735.                                                  DirName=NULL;
  736.                                                  DirNameLength+=256;
  737.                                               }
  738.                                            else
  739.                                               {
  740.                                                  DosError=IoErr();
  741.                                               }
  742.                                         }
  743.                                      while (!DosError);
  744.                                      if (!DosError && !(DosError=ReadDir(DirLock)))
  745.                                         {
  746.                                            NodeDataTmp=NULL;
  747.                                            NodeLength=0;
  748.                                            ReadMessage(DirLock);
  749.                                            NodeLength+=PrintMessage();
  750.                                            NodeLength+=PrintDir(Name,DirName);
  751.                                            if (Main)
  752.                                               {
  753.                                                  NodeLength+=PrintNodeText("\n\n"
  754.                                                                            "@{\x22""About the manual browser\x22 LINK \x22""AbOuT\x22}\n");
  755.                                               }
  756.  
  757.                                            if ((NodeData=Malloc(NodeLength+1)))
  758.                                               {
  759.                                                  NodeDataTmp=NodeData;
  760.                                                  PrintMessage();
  761.                                                  PrintDir(Name,DirName);
  762.                                                  if (Main)
  763.                                                     {
  764.                                                        PrintNodeText("\n\n"
  765.                                                                      "@{\x22""About the manual browser\x22 LINK \x22""AbOuT\x22}\n");
  766.                                                     }
  767.                                                  ((struct opNodeIO *)Message)->onm_DocBuffer=NodeData;
  768.                                                  ((struct opNodeIO *)Message)->onm_BuffLen=NodeLength;
  769.                                                  UnLock(OldCurrDir);
  770.                                                  OldCurrDir=DirLock;
  771.                                               }
  772.                                            else
  773.                                               {
  774.                                                  DosError=IoErr();
  775.                                               }
  776.                                            Free(MessageText);
  777.                                            MessageText=NULL;
  778.                                         }
  779.                                      if (!NodeData) UnLock(DirLock);
  780.                                      if (DirName)
  781.                                         {
  782.                                            Free(DirName);
  783.                                         }
  784.                                   }
  785.                                else
  786.                                   {
  787.                                      DosError=IoErr();
  788.                                   }
  789.                                CurrentDir(OldCurrDir);
  790.                                if (DosError)
  791.                                   {
  792.                                      static char FaultString[84];
  793.                                      ((struct opNodeIO *)Message)->onm_DocBuffer=FaultString;
  794.                                      ((struct opNodeIO *)Message)->onm_BuffLen=Fault(DosError,NULL,FaultString,sizeof(FaultString));
  795.                                   }
  796.                                return TRUE;
  797.                             }
  798.                             break;
  799.  
  800.          case HM_CLOSENODE: {
  801.                                if (NodeData) Free(NodeData);
  802.                                NodeData=NULL;
  803.                                FreeDirNodes(&DirectoryList);
  804.                                FreeDirNodes(&FileList);
  805.                                return TRUE;
  806.                             }
  807.                             break;
  808.       }
  809.    return FALSE;
  810. }
  811.